package com.tomehay.termprojectmanage_server.service.impl;

import com.tomehay.termprojectmanage_server.mapper.CodeMapper;
import com.tomehay.termprojectmanage_server.pojo.Model.Code;
import com.tomehay.termprojectmanage_server.service.CodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import org.springframework.core.io.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * (Code表)服务实现类
 *
 * @author makejava
 * @since 2023-06-24 15:54:09
 */
@Service("codeService")
public class CodeServiceImpl implements CodeService {

    @Value("${filePath}")
    private String filePath;

    @Autowired
    private CodeMapper codeMapper;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Code selectById(Integer id) {
        return this.codeMapper.selectByPrimaryKey(id.longValue());
    }

    /**
     * 分页查询
     *
     * @param start 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    @Override
    public List<Code> selectPage(int start, int limit) {
//        return this.codeMapper.selectPage(start, limit);
        return null;
    }

    /**
     * 查询所有
     *
     * @return 实例对象的集合
     */
     @Override
     public List<Code> selectAll() {
        return this.codeMapper.queryAll();
     }
     
    /**
     * 根据条件查询
     *
     * @return 实例对象的集合
     */
    @Override
    public List<Code> selectList(Code code) {
//        return this.codeMapper.selectList(code);
        return null;
    }
    
    /**
     * 新增数据
     *
     * @param code 实例对象
     * @return 实例对象
     */
    @Override
    public int insert(Code code, Integer pid) {
        code.setCreateTime(new Date(System.currentTimeMillis()));
        code.setUrl(filePath + "/" + pid + "/" + code.getGno() + "/" + code.getGmno() + "/" + code.getName());
        File file = new File(filePath + "/" + pid + "/" + code.getGno() + "/" + code.getGmno() + "/" + code.getName() + ".txt");
        createFile(file);
        return this.codeMapper.insert(code);
    }

    /**
     * 批量新增
     *
     * @param codes 实例对象的集合
     * @return 生效的条数
     */
    @Override
    public int batchInsert(List<Code> codes) {
        return this.codeMapper.insertBatch(codes);
    }

    /**
     * 修改数据
     *
     * @param code 实例对象
     * @return 实例对象
     */
    @Override
    public Code update(Code code) {
        this.codeMapper.updateByPrimaryKeySelective(code);
        return this.selectById(code.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public int deleteById(Integer id) {
        return this.codeMapper.deleteByPrimaryKey(id.longValue());
    }
    
    /**
     * 查询总数据数
     *
     * @return 数据总数
     */
     @Override
     public int count(){
        return this.codeMapper.count();
     }

    @Override
    public void uploadCodeBatch(Integer pid, Integer gmno, Integer gno, List<MultipartFile> files) {
        try {
            //判断文件夹是否存在，不存在时，创建文件夹
            File directoryFile = new File(filePath);
            if (!directoryFile.exists()) {
                //创建多个文件夹
                directoryFile.mkdirs();
            }

            //判断上传文件个数是否为0
            if (files.size() > 0) {
                for (MultipartFile multipartFile : files) {
                    if (!multipartFile.isEmpty()) {
                        String name = multipartFile.getOriginalFilename();
                        multipartFile.transferTo(new File(filePath + name));
                        Code code = new Code();
                        code.setUrl(filePath + name);
                        code.setGmno(gmno);
                        code.setGno(gno);
                        code.setName(name);
                        codeMapper.insertSelective(code);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void uploadCode(String no, String description, Integer pid, Integer gmno, Integer gno, MultipartFile file) {
        try {

            //判断文件是否为空，不为空时，保存文件
            if (!file.isEmpty()) {
                //获取文件名
                String name = file.getOriginalFilename();
                File file1 = new File(filePath +"/" + pid + "/" + gmno + "/" + gno + "/" + name);
                createFile(file1);
                file.transferTo(file1);
                Code code = new Code();
                code.setCreateTime(new Date(System.currentTimeMillis()));
                code.setUrl(filePath + "/" + pid + "/" + gmno + "/" + gno + "/" + name);
                code.setNo(no);
                code.setDescription(description);
                code.setName(name);
                code.setGmno(gmno);
                code.setGno(gno);
                codeMapper.insertSelective(code);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public ResponseEntity<InputStreamResource> download(Integer id) {
        try {
            // 读取文件
            Code code = codeMapper.selectByPrimaryKey(id.longValue());
            FileSystemResource file = new FileSystemResource(code.getUrl());

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getFilename()));

            return ResponseEntity
                    .ok()
                    .headers(headers)
                    .contentLength(file.contentLength())
                    .contentType(MediaType.parseMediaType("application/octet-stream"))
                    .body(new InputStreamResource(file.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Code> listByProjectId(Integer projectId) {
        List<Code> codes = codeMapper.listAllByGno(projectId);
        return codes;
    }

    @Override
    public ResponseEntity<Resource> getDetail(Integer cid) {
        Code code = codeMapper.selectByPrimaryKey(cid.longValue());
        // 创建一个文件对象，指定要发送的文件路径
        File file = new File(code.getUrl());
        // 创建一个文件资源对象，用于封装文件内容
        Resource resource = new FileSystemResource(file);
        // 创建一个Http头对象，用于设置响应的属性
        HttpHeaders headers = new HttpHeaders();
        // 设置响应的内容类型为APPLICATION_OCTET_STREAM，表示任意的二进制数据
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        // 设置响应的内容长度为文件的大小
        headers.setContentLength(file.length());
        // 设置响应的内容描述为附件形式，并指定文件名
        headers.setContentDispositionFormData("attachment", file.getName());
        // 创建一个响应实体对象，用于封装响应的状态码，头部信息和正文内容
        ResponseEntity<Resource> responseEntity = new ResponseEntity<>(resource, headers, 200);
        // 返回响应实体对象
        return responseEntity;
    }

    @Override
    public Integer updateCode(Integer cid, MultipartFile file) {
        try {
            Code code = codeMapper.selectByPrimaryKey(cid.longValue());
            File file1 = new File(code.getUrl());
            if (file1.exists()) {
                file1.delete();
            }
            createFile(file1);
            file.transferTo(file1);
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        }
        return 1;
    }

    public static void createFile(File file) {
        if (file.exists()) {
            System.out.println("File exists");
        } else {
//            System.out.println("File not exists, create it ...");
            //getParentFile() 获取上级目录(包含文件名时无法直接创建目录的)
            if (!file.getParentFile().exists()) {
//                System.out.println("not exists");
                //创建上级目录
                file.getParentFile().mkdirs();
            }
            try {
                //在上级目录里创建文件
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

